home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Game-Power
/
Amiga Game-Power.iso
/
pd mix ii
/
access
/
hddriver
/
driver
/
trackcache.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-20
|
4KB
|
209 lines
/*
* Copyright 1987 Alan Kent
*
* Permission is granted to redistribute this code as long
* as this message is retained in the code and the code is
* not sold without written permission from the author.
*
* UUCP: {seismo,hplabs,mcvax,ukc,nttlab}!munnari!goanna.oz!ajk
* ACSnet: ajk@goanna.oz
* ARPA: munnari!goanna.oz!ajk@SEISMO.ARPA
*/
#include "hd.h"
extern struct Node *RemTail ();
#define CACHE_SIZE 10
static struct cache {
struct Node node;
struct posn posn;
UBYTE * buf;
} cache[ CACHE_SIZE ];
static struct List history;
void
clear_all ()
{
register int i;
register struct cache *c;
NewList ( &history );
for ( i = 0; i < CACHE_SIZE; i++ ) {
c = &cache[i];
c->posn.cylinder = -1;
c->node.ln_Pri = 0;
AddTail ( &history , c );
}
}
void
flush_all ()
{
}
int
init_cache ()
{
int i;
for ( i = 0; i < CACHE_SIZE; i++ ) {
if ( ( cache[i].buf = (UBYTE *) AllocMem (
(LONG)HD_SECTOR * first.sectors , (LONG)MEMF_CLEAR ) ) == NULL ) {
while ( --i >= 0 )
FreeMem ( cache[i].buf , (LONG)HD_SECTOR * first.sectors );
return ( -1 );
}
}
clear_all ();
return ( 0 );
}
void
free_cache ()
{
register int i;
for ( i = 0; i < CACHE_SIZE; i++ )
FreeMem ( cache[i].buf , (LONG)HD_SECTOR * first.sectors );
}
UBYTE *
read_cache ( posn )
struct posn *posn;
{
register struct cache *c;
int status;
static UBYTE single_buf[ HD_SECTOR ];
/* see if track is in the cache */
for ( c = (struct cache *) history.lh_Head;
c->node.ln_Succ != NULL;
c = (struct cache *) c->node.ln_Succ ) {
if ( posn->cylinder == c->posn.cylinder
&& posn->surface == c->posn.surface ) {
/* recalculate priority so is not pushed out of list */
Remove ( c );
calc_priority ( c );
Enqueue ( &history , c );
return ( &c->buf[ posn->sector * (LONG)HD_SECTOR ] );
}
}
/* ok, decrease cache weights so new tracks have better chance */
for ( c = (struct cache *) history.lh_Head;
c->node.ln_Succ != NULL;
c = (struct cache *) c->node.ln_Succ ) {
if ( c->node.ln_Pri > 0 )
c->node.ln_Pri--;
}
/* not in cache */
c = (struct cache *) RemTail ( &history );
c->posn = *posn;
status = read_track ( &c->posn , c->buf );
if ( status != 0 ) {
AddTail ( &history , c );
c->posn.cylinder = -1;
status = read_sector ( &c->posn , &single_buf[0] );
if ( status != 0 )
status = read_sector ( &c->posn , &single_buf[0] );
if ( status != 0 )
status = read_sector ( &c->posn , &single_buf[0] );
if ( status != 0 )
return ( NULL );
return ( &single_buf[0] );
}
calc_priority ( c );
Enqueue ( &history , c );
return ( &c->buf[ posn->sector * (LONG)HD_SECTOR ] );
}
void
write_cache ( posn , buf )
register struct posn *posn;
UBYTE *buf;
{
register struct cache *c;
/* if in cache, make sure updated in cache */
for ( c = (struct cache *) history.lh_Head;
c->node.ln_Succ != NULL;
c = (struct cache *) c->node.ln_Succ ) {
if ( posn->cylinder == c->posn.cylinder
&& posn->surface == c->posn.surface ) {
/* update cache */
copy_sector ( buf , &c->buf[ posn->sector * (LONG)HD_SECTOR ] );
break;
}
}
write_sector ( posn , buf );
}
static
calc_priority ( c )
struct cache *c;
{
register UBYTE *p;
register LONG type , subtype;
register int sector;
register int priority;
/* ok, now lets peek inside the sectors to see if this track */
/* contains anything juicy. Directory entries get extra points */
/* because of the way they are scattered all over the place. */
/* Data blocks get less because they are only likely to be used */
/* once. */
priority = 0;
for ( sector = 0, p = c->buf;
sector < first.sectors;
sector++, p += HD_SECTOR ) {
type = ((LONG*)p) [ 0 ];
subtype = ((LONG*)p) [ 127 ];
if ( type == 2 && subtype == 2 /* File Header */
|| type == 2 && subtype == -3 /* User Directory */
|| type == 16 && subtype == -3 ) /* file extension */
priority += 2;
if ( type == 8 ) /* data block */
priority += 1;
}
c->node.ln_Pri = priority;
}